package services;

import java.util.Collection;
import java.util.Date;
import java.util.HashSet;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import repositories.CustomerRepository;
import security.Authority;
import security.LoginService;
import security.UserAccount;
import domain.Administrator;
import domain.Auction;
import domain.Bid;
import domain.Comment;
import domain.Customer;
import domain.Gallery;
import domain.OwnershipHistory;
import domain.Painting;
import forms.CustomerForm;

@Service
@Transactional
public class CustomerService {
	// Managed Repository

	@Autowired
	private CustomerRepository customerRepository;

	// Managed Services
	@Autowired
	private AdministratorService administratorService;
	
	// Constructors

	public CustomerService() {
		super();
	}

	// Simple CRUD methods

	public Customer create() {
		Customer result;
		UserAccount userAccount;
		Authority authority;
		Collection<Gallery> galleries;
		Collection<OwnershipHistory> ownershipHistories;
		Collection<Painting> paintings;
		Collection<Auction> auctions;
		Collection<Bid> bids;
		Collection<Comment> comments;

		authority = new Authority();
		galleries = new HashSet<Gallery>();
		ownershipHistories = new HashSet<OwnershipHistory>();
		paintings = new HashSet<Painting>();
		auctions = new HashSet<Auction>();
		bids = new HashSet<Bid>();
		comments = new HashSet<Comment>();

		userAccount = new UserAccount();
		authority.setAuthority("CUSTOMER");
		userAccount.addAuthority(authority);

		result = new Customer();
		result.setUserAccount(userAccount);
		result.setGalleries(galleries);
		result.setOwnershipHistories(ownershipHistories);
		result.setPaintings(paintings);
		result.setAuctions(auctions);
		result.setBids(bids);
		result.setComments(comments);

		return result;
	}

	public Collection<Customer> findAll() {
		Collection<Customer> result;

		result = customerRepository.findAll();

		return result;
	}

	public Customer findOne(int userId) {
		Customer result;

		result = customerRepository.findOne(userId);

		return result;
	}

	@SuppressWarnings("deprecation")
	public void save(Customer customer) {
		Assert.notNull(customer);
		Date currentMoment;
		currentMoment = new Date();

		Assert.isTrue((customer.getCreditCard().getExpirationYear() - 1900) >= currentMoment
				.getYear());
		if ((customer.getCreditCard().getExpirationYear() - 1900) == currentMoment
				.getYear()) {
			Assert.isTrue((customer.getCreditCard().getExpirationMonth() - 1) > currentMoment
					.getMonth());
		}
		if (customer.getId() == 0) {
			Assert.isNull(findByUsername(customer.getUserAccount()
					.getUsername()));
		}
		Assert.isNull(administratorService.findByUsername(customer
				.getUserAccount().getUsername()));

		customerRepository.save(customer);
	}

	// Other Business Methods
	public Customer findByPrincipal() {
		Customer result;
		UserAccount userAccount;

		userAccount = LoginService.getPrincipal();
		Assert.notNull(userAccount);

		result = findByUserAccount(userAccount);
		Assert.notNull(result);

		return result;
	}

	public Customer findByUserAccount(UserAccount userAccount) {
		Assert.notNull(userAccount);
		Customer result;

		result = customerRepository.findByUserAccountId(userAccount.getId());

		return result;
	}

	public Customer findByUsername(String username) {
		Assert.notNull(username);
		Customer result;
		result = customerRepository.findByUsername(username);
		return result;
	}

	// Reconstruction method
	public Customer reconstruct(CustomerForm customerForm) {
		Assert.notNull(customerForm);
		Customer result;
		Md5PasswordEncoder encoder = new Md5PasswordEncoder();
		String password = customerForm.getPassword();
		String hash = encoder.encodePassword(password, null);

		result = create();
		result.getUserAccount().setUsername(customerForm.getUsername());
		result.getUserAccount().setPassword(hash);
		result.setName(customerForm.getName());
		result.setSurname(customerForm.getSurname());
		result.setEmail(customerForm.getEmail());
		result.setCreditCard(customerForm.getCreditCard());

		return result;
	}

	public Collection<Customer> findByMorePaintings() {
		Collection<Customer> res;
		Administrator principal;
		principal = administratorService.findByPrincipal();
		Assert.isTrue(principal instanceof Administrator);
		res = customerRepository.findByMorePaintings();
		return res;
	}
	

	public Collection<Customer> findByMoreComments() {
		Collection<Customer> res;
		Administrator principal;
		principal = administratorService.findByPrincipal();
		Assert.isTrue(principal instanceof Administrator);
		res = customerRepository.findByMoreComments();
		Assert.notNull(res);
		return res;

	}

	public Customer findOwnerByPainting(Painting painting) {
		Assert.notNull(painting);
		Customer result;

		result = customerRepository.findOwnerByPaintingId(painting.getId());

		return result;
	}

}
